using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;

namespace ClassifierLib
{
    /// <summary>
    /// Provides a training set of randomised values
    /// </summary>
    public class RandomDiscreteTrainingSet : TrainingSet
    {
        private int _count;
        private int _vectorLength;

        /// <summary>
        /// Creates a random training set of 1000 values
        /// </summary>
        public RandomDiscreteTrainingSet()
        {
            _count = 1000; // default training set size
            _vectorLength = 6; // default vector length

            this.ActionFactory = new DiscreteActionFactory();
        }

        /// <summary>
        /// Creates a random training set of specified size
        /// </summary>
        /// <param name="Count">Number of training values</param>
        /// <param name="Length">Length of training value vector</param>
        public RandomDiscreteTrainingSet(int Count, int Length)
        {
            this.Count = Count;
            this.VectorLength = Length;

            this.ActionFactory = new DiscreteActionFactory();
        }

        private int _outputStateCount;
        public int OutputStateCount
        {
            get
            {
                return (ActionFactory as DiscreteActionFactory).OutputCount;
            }
            set
            {
                (ActionFactory as DiscreteActionFactory).OutputCount = value;
                OnPropertyChanged("OutputStateCount");
            }
        }

        public override TrainingValue GetNext()
        {
            Count--;

            Debug.Assert(Count >= 0,"GetNext called on trainingset after finised flag set");

            // create random state vector
            List<Double> values = new List<double>();
           
            for (int i = 0; i < _vectorLength; i++)
            {
                values.Add(PersistantRandom.Instance.Next(2));
            }
            
            return new TrainingValue(new Environment.State(values), ActionFactory.Instance());
        }


        public override bool IsFinished
        {
            get
            {
                return (Count<=0);
            }
        }

        /// <summary>
        /// Sets the number of random values to generate before completion
        /// </summary>
        [CategoryAttribute("Settings"), Browsable(true), ReadOnly(false), BindableAttribute(false), DesignOnly(false), DescriptionAttribute("Number of items in training set")]
        public int Count
        {
            get
            {
                return _count;
            }
            set
            {
                _count = value;
                OnPropertyChanged("Count");

                if (_count < 0)
                    OnPropertyChanged("IsFinished");
            }
        }


        [CategoryAttribute("Settings"), Browsable(true), ReadOnly(false), BindableAttribute(false), DesignOnly(false), DescriptionAttribute("length in bits of vector returned by training set")]
        public int VectorLength
        {
            get
            {
                return _vectorLength;
            }
            set
            {
                _vectorLength = value;
                OnPropertyChanged("VectorLength");
            }
        }
    }
}
